﻿using System.Collections.Generic;
using AzureGames.Domain.Services;
using InMemory = AzureGames.Data.InMemory;
using AzureGames.Domain.Handlers;
using Model = AzureGames.Model;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using AzureGames.Data;
using System.Threading;
using AzureGames.Domain.Models;
using System.Linq;
using AzureGames.Domain.Tests.Helper;
using AzureGames.Model;

namespace AzureGames.Domain.Tests
{
    /// <summary>
    ///This is a test class for GetGameDefinitionTest and is intended
    ///to contain all GetGameDefinitionTest Unit Tests
    ///</summary>
    [TestClass()]
    public class GameOptionsTests
    {
        private static string[] playerIDs = new string[]
                                              {
                                                  new Guid("DF2AA2FD-6AA8-474F-B29B-BCCD8247D397").ToString(),
                                                  new Guid("2F851A61-249B-4942-9FE4-2276D39183EF").ToString(),
                                                  new Guid("328C8086-B7FB-4F65-A0E2-6F2AE40E1300").ToString()
                                              };

        [TestMethod()]
        public void GameOptionsTest()
        {
            // create in memory repositories
            IBoardRepository boardRepository = new InMemory.BoardRepository();
            IGameDefinitionRepository gameDefinitionRepository = new InMemory.GameDefinitionRepository();
            INotificationRepository notificationRepository = new InMemory.NotificationRepository();
            IUserRepository userRepository = new InMemory.UserRepository();
            IUserStatisticsRepository userstatisticsRepository = new InMemory.StatisticsRepository();
            IGameStatisticsRepository gamestatisticsRepository = new InMemory.StatisticsRepository();
            IAIPlayerRepository aiPlayerRepository = new InMemory.PlayerRepository();
            
            IPlayerRepository playerRepository = new InMemory.PlayerRepository();
            NotificationService.Instance.IntializeNotificationService(notificationRepository, boardRepository);

            GetGamePlayOptions getGamePlayOptions = new GetGamePlayOptions(gameDefinitionRepository, playerRepository, boardRepository, aiPlayerRepository);
            CreateNewGame createNewGame = new CreateNewGame(boardRepository, gameDefinitionRepository, playerRepository, userstatisticsRepository, gamestatisticsRepository);
            RegisterNewGame registerNewGame = new RegisterNewGame(boardRepository, gameDefinitionRepository, notificationRepository, playerRepository, userstatisticsRepository, gamestatisticsRepository);
            UpdateBoard updateGameBoard = new UpdateBoard(gameDefinitionRepository, boardRepository, userstatisticsRepository, gamestatisticsRepository, playerRepository, notificationRepository);
            GetBoard getBoard = new GetBoard(boardRepository);

            GamePlayOptions options = getGamePlayOptions.Execute(1, playerIDs[0], 10);

            Assert.AreEqual(options.AIPlayers.Count, 1);
            Assert.AreEqual(options.ActiveGames.Count, 0);
            Assert.AreEqual(options.ChallengePlayers.Count, 0);
            Assert.AreEqual(options.ContactPlayers.Count, 0);
            Assert.AreEqual(options.CurrentPlayer.ID, playerIDs[0]);
            Assert.IsTrue(options.Instructions.Length > 0);
            Assert.AreEqual(options.ID, 1);
            Assert.IsTrue(options.Instructions.Length > 0);
            Assert.AreEqual(options.IsAuthenticated, true);
            Assert.AreEqual(options.Messages.Count, 0);
            Assert.AreEqual(options.Name, "Amazons");

            // ai player
            var aiPlayer = options.AIPlayers[0].ID;

            // create some games
            var board1 = registerNewGame.Execute(1, playerIDs[0]);
            var board2 = registerNewGame.Execute(1, playerIDs[1]);
            var board3 = registerNewGame.Execute(1, playerIDs[0]);
            var board4 = registerNewGame.Execute(1, playerIDs[2]);
            var board5 = registerNewGame.Execute(1, playerIDs[1]);
            var board6 = registerNewGame.Execute(1, playerIDs[2]);

            var board7 = createNewGame.Execute(1, new List<string> { playerIDs[0], aiPlayer });
            var board8 = createNewGame.Execute(1, new List<string> { playerIDs[2], aiPlayer });

            Assert.AreEqual(board1.ID, board2.ID);
            Assert.AreEqual(board3.ID, board4.ID);
            Assert.AreEqual(board5.ID, board6.ID);
            Assert.AreNotEqual(board7.ID, board8.ID);

            options = getGamePlayOptions.Execute(1, playerIDs[0], 10);

            Assert.AreEqual(options.ActiveGames.Count, 3);
            Assert.AreEqual(options.ActiveGames[0].BoardID, board2.ID);
            Assert.AreEqual(options.ActiveGames[0].GamePlayers[0].ID, playerIDs[0]);
            Assert.AreEqual(options.ActiveGames[0].State, "1");
            Assert.AreEqual(options.ActiveGames[1].GamePlayers[0].ID, playerIDs[0]);
            Assert.AreEqual(options.ActiveGames[1].State, "1");
            Assert.AreEqual(options.ActiveGames[2].GamePlayers[1].ID, aiPlayer);
            Assert.AreEqual(options.ActiveGames[2].State, "1");
            Assert.AreEqual(options.ActiveGames[2].BoardID, board7.ID);

            // cancel a game
            var boardModel = getBoard.Execute(board7.ID);
            boardModel.State = Board.Cancelled;
            updateGameBoard.Execute(boardModel);            

            options = getGamePlayOptions.Execute(1, playerIDs[0], 10);
            Assert.AreEqual(options.ActiveGames.Count, 2);
        }
    }
}